package com.atguigu.commonutils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;

/**
 * @author He Wentao
 * @since 2022/9/16 21:24
 */

public class JwtUtils {
    // 设置 toKen 过期时间
    public static final long EXPIRE = 1000 * 60 * 60 * 24;
    // 密钥，会根据这个密钥，对字符串进行加密
    public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO”";

    /**
     * 生成 Token 字符串的方法
     *
     * @param id       要加密的字符串
     * @param nickname 要加密的字符串
     * @return 加密后的 Token 字符串
     */
    public static String getJwtToken(String id, String nickname) {

        return Jwts.builder() // 构建 JWT 字符串对象
                //  设置 JWT 头部信息   <固定>
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")

                // 设置分类，任意字符即可
                .setSubject("user")

                // 设置过期时间
                .setIssuedAt(new Date())   // 当前时间
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE)) // 过期时间

                // 设置 Token 要加密的信息，可以有多个
                .claim("id", id)
                .claim("nickname", nickname)

                // 设置根据什么方式 和 加密密钥，进行加密
                // 注意：key 的长度必须符合签名算法的要求（避免生成弱密钥）
                // HS256：bit 长度要>=256，即字节长度>=32
                // HS384：bit 长度要>=384，即字节长度>=48
                // HS512：bit 长度要>=512，即字节长度>=64
                .signWith(SignatureAlgorithm.HS256, APP_SECRET.getBytes(StandardCharsets.UTF_8))
                .compact();
    }

    /**
     * 判断 Token 是否有效
     *
     * @param jwtToken Token
     * @return true 有效 |  false 无效
     */
    public static boolean checkToken(String jwtToken) {
        if (StringUtils.isEmpty(jwtToken)) return false;
        try {
            Jwts.parser().setSigningKey(APP_SECRET.getBytes(StandardCharsets.UTF_8)).parseClaimsJws(jwtToken);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 也是判断 Token 是否有效，只不过这里是从 Request请求头 中获到 Token
     * @param request  请求对象
     * @return  true 有效 |  false 无效
     */
    public static boolean checkToken(HttpServletRequest request) {
        try {
            String jwtToken = request.getHeader("token");
            if (StringUtils.isEmpty(jwtToken)) return false;
            Jwts.parser().setSigningKey(APP_SECRET.getBytes(StandardCharsets.UTF_8)).parseClaimsJws(jwtToken);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 根据 Token 获取到加密数据
     * @param request 请求对象
     * @return 解密后的 id
     */
    public static String getMemberIdByJwtToken(HttpServletRequest request) {
        String jwtToken = request.getHeader("token");

        if (StringUtils.isEmpty(jwtToken)) return "";

        // 进行解密
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET.getBytes(StandardCharsets.UTF_8)).parseClaimsJws(jwtToken);

        // 获取到 Token 体中的加密数据
        Claims claims = claimsJws.getBody();

        // 返回指定加密数据
        return (String) claims.get("id");

    }

    /**
     *  根据 String 类型 Token 获取用户 id
     * @param token token
     * @return 用户 id
     */
    public static String getMemberInfoByToken(String token){
        if (StringUtils.isEmpty(token)) return "";

        // 进行解密
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET.getBytes(StandardCharsets.UTF_8)).parseClaimsJws(token);

        // 获取到 Token 体中的加密数据
        Claims claims = claimsJws.getBody();

        // 返回指定加密数据
        return (String) claims.get("id");
    }

}
